#pragma once

#include "../umlmodel_global.h"

#include <memory>
#include <vector>

#include "MessageKind.h"
#include "MessageSort.h"
#include "NamedElement.h"

using std::make_shared;
using std::shared_ptr;
using std::vector;

namespace uml {
class Connector;
class Interaction;
class MessageEnd;
class NamedElement;
class Namespace;
class ValueSpecification;

/// <summary>
/// Message
/// A Message defines a particular communication between Lifelines of an
/// Interaction.
/// </summary>
class UMLMODEL_EXPORT Message : public NamedElement {

public: // Constructors and destructors
    explicit Message(const QString& umlType="uml::Message");

public: // JsonSerializable override
    void fromJson(const QJsonObject& json, QStringList& errorList) override;
    void toJson(QJsonObject& json) override;

public: // Methods
    /// <summary>
    /// isDistinguishableFrom
    /// The query isDistinguishableFrom() specifies that any two Messages may coexist in
    /// the same Namespace, regardless of their names.
    /// </summary>
    bool isDistinguishableFrom(shared_ptr<NamedElement> n, shared_ptr<Namespace> ns) const override;

public: // Properties
    /// <summary>
    /// arguments getter
    /// The arguments of the Message.
    /// </summary>
    vector<shared_ptr<ValueSpecification>>& arguments();

    /// <summary>
    /// connector getter
    /// The Connector on which this Message is sent.
    /// </summary>
    shared_ptr<Connector> connector() const;

    /// <summary>
    /// connector setter
    /// The Connector on which this Message is sent.
    /// </summary>
    void setConnector(shared_ptr<Connector> value);

    /// <summary>
    /// interaction getter
    /// The enclosing Interaction owning the Message.
    /// </summary>
    shared_ptr<Interaction> interaction() const;

    /// <summary>
    /// interaction setter
    /// The enclosing Interaction owning the Message.
    /// </summary>
    void setInteraction(shared_ptr<Interaction> value);

    /// <summary>
    /// messageKind getter
    /// The derived kind of the Message (complete, lost, found, or unknown).
    /// </summary>
    MessageKind messageKind() const;

    /// <summary>
    /// messageKind setter
    /// The derived kind of the Message (complete, lost, found, or unknown).
    /// </summary>
    void setMessageKind(MessageKind value);

    /// <summary>
    /// messageSort getter
    /// The sort of communication reflected by the Message.
    /// </summary>
    MessageSort messageSort() const;

    /// <summary>
    /// messageSort setter
    /// The sort of communication reflected by the Message.
    /// </summary>
    void setMessageSort(MessageSort value);

    /// <summary>
    /// receiveEvent getter
    /// References the Receiving of the Message.
    /// </summary>
    shared_ptr<MessageEnd> receiveEvent() const;

    /// <summary>
    /// receiveEvent setter
    /// References the Receiving of the Message.
    /// </summary>
    void setReceiveEvent(shared_ptr<MessageEnd> value);

    /// <summary>
    /// sendEvent getter
    /// References the Sending of the Message.
    /// </summary>
    shared_ptr<MessageEnd> sendEvent() const;

    /// <summary>
    /// sendEvent setter
    /// References the Sending of the Message.
    /// </summary>
    void setSendEvent(shared_ptr<MessageEnd> value);

    /// <summary>
    /// signature getter
    /// The signature of the Message is the specification of its content. It refers
    /// either an Operation or a Signal.
    /// </summary>
    shared_ptr<NamedElement> signature() const;

    /// <summary>
    /// signature setter
    /// The signature of the Message is the specification of its content. It refers
    /// either an Operation or a Signal.
    /// </summary>
    void setSignature(shared_ptr<NamedElement> value);

private: // Fields
    /// <summary>
    /// arguments
    /// The arguments of the Message.
    /// </summary>
    vector<shared_ptr<ValueSpecification>> arguments_;

    /// <summary>
    /// connector
    /// The Connector on which this Message is sent.
    /// </summary>
    shared_ptr<Connector> connector_;

    /// <summary>
    /// interaction
    /// The enclosing Interaction owning the Message.
    /// </summary>
    shared_ptr<Interaction> interaction_;

    /// <summary>
    /// messageKind
    /// The derived kind of the Message (complete, lost, found, or unknown).
    /// </summary>
    MessageKind messageKind_ = MessageKind::kcomplete;

    /// <summary>
    /// messageSort
    /// The sort of communication reflected by the Message.
    /// </summary>
    MessageSort messageSort_ = MessageSort::ksynchCall;

    /// <summary>
    /// receiveEvent
    /// References the Receiving of the Message.
    /// </summary>
    shared_ptr<MessageEnd> receiveEvent_;

    /// <summary>
    /// sendEvent
    /// References the Sending of the Message.
    /// </summary>
    shared_ptr<MessageEnd> sendEvent_;

    /// <summary>
    /// signature
    /// The signature of the Message is the specification of its content. It refers
    /// either an Operation or a Signal.
    /// </summary>
    shared_ptr<NamedElement> signature_;

};

} // namespace uml
